#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <unistd.h>
#include <pthread.h>

using namespace std;

#define NUM 4

class threadData
{
public:
    threadData(int number)
    {
        threadname = "thread-" + to_string(number);
    }

public:
    string threadname;
};

int tickets = 1000; // 用多线程，模拟一轮抢票

void *getTicket(void *args)
{
    threadData *td = static_cast<threadData *>(args);
    const char *name = td->threadname.c_str();
    while (true)
    {
        if(tickets > 0)
        {
            usleep(1000);
            printf("who=%s, get a ticket: %d\n", name, tickets); // ?
            tickets--;
        }
        else
            break;
    }
    printf("%s ... quit\n", name);
    return nullptr;
}

int main()
{
    vector<pthread_t> tids;
    vector<threadData *> thread_datas;
    for (int i = 1; i <= NUM; i++)
    {
        pthread_t tid;
        threadData *td = new threadData(i);
        thread_datas.push_back(td);
        pthread_create(&tid, nullptr, getTicket, thread_datas[i - 1]);
        tids.push_back(tid);
    }

    for (auto thread : tids)
    {
        pthread_join(thread, nullptr);
    }

    for (auto td : thread_datas)
    {
        delete td;
    }
    return 0;
}





// #include <iostream>
// #include <pthread.h>
// #include <vector>
// #include <string>
// #include <unistd.h>

// using namespace std;

// #define NUM 3

// int *p = nullptr;
// //线程局部存储
// __thread int val = 100;

// class ThreaInfo
// {
// public:
//     ThreaInfo(const string &threadname)
//     :threadname_(threadname)
//     {}

// public:
//     string threadname_;
// };

// string toHex(pthread_t tid)
// {
//     char buffer[64];
//     snprintf(buffer, sizeof(buffer), "%p", tid);
//     return buffer;
// }

// void *threadroutine(void *args)
// {
//     int i = 0;
//     ThreaInfo *ti = static_cast<ThreaInfo*>(args);

//     while(i < 10)
//     {
//         cout << ti->threadname_.c_str() << " is running, tid: " << toHex(pthread_self()) << ", pid: " << getpid()  << ", val: " << val << ", &val: " << &val << endl;
//         i++;
//         val++;
//         usleep(10000);
//     }

//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     for(int i = 0; i < NUM; i++)
//     {
//         pthread_t tid;
//         ThreaInfo *ti = new ThreaInfo("Thread-"+to_string(i));
//         pthread_create(&tid, nullptr, threadroutine, ti);

//         tids.push_back(tid);
//         usleep(1000);
//     }

//     for(auto tid:tids)
//     {
//         pthread_join(tid, nullptr);
//     }
//     return 0;
// }






// class ThreaInfo
// {
// public:
//     ThreaInfo(const string &threadname)
//     :threadname_(threadname)
//     {}

// public:
//     string threadname_;
// };

// string toHex(pthread_t tid)
// {
//     char buffer[64];
//     snprintf(buffer, sizeof(buffer), "%p", tid);
//     return buffer;
// }

// void *threadroutine(void *args)
// {
//     int i = 0;
//     int num = 0;
//     ThreaInfo *ti = static_cast<ThreaInfo*>(args);
//     while(i < 10)
//     {
//         cout << ti->threadname_.c_str() << " is running, tid: " << toHex(pthread_self()) << ", pid: " << getpid()  << ", num: " << num << ", &num: " << toHex((pthread_t)&num) << endl;
//         i++;
//         num++;
//         usleep(10000);
//     }
//     delete ti;
//     return nullptr;
// }

// int main()
// {
//     vector<pthread_t> tids;
//     for(int i = 0; i < NUM; i++)
//     {
//         pthread_t tid;
//         ThreaInfo *ti = new ThreaInfo("Thread-"+to_string(i));
//         pthread_create(&tid, nullptr, threadroutine, ti);

//         tids.push_back(tid);
//         // sleep(1);
//         usleep(1000);

//     }

//     for(auto tid:tids)
//     {
//         pthread_join(tid, nullptr);
//     }
//     return 0;
// }